//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddkit.h>
#include "ippIP.h"
#include "ccamera.h"

#define _ALIGN4(adr) ((((Ipp32u)(adr))+3)&(~3))
void *  __cdecl memcpy(void *, const void *, size_t);

extern unsigned long *g_pMmxData;
static unsigned int s_dummyFlag = 0x3; // Let all WMMX registers be saved.
void SaveWMMXRegisters(ulong_t *pMmxData, uint_t *pFlags);
void RestoreWMMXRegisters(ulong_t *pMmxData);

IppStatus ASM_ippiYCbCr422RszRot_8u_P3R(const Ipp8u *pSrc[3],
        int srcStep[3], IppiSize srcSize, Ipp8u *pDst[3],
	    int dstStep[3], IppiSize dstSize, IppCameraInterpolation interpolation,
	    IppCameraRotation rotation, int rcpRatiox, int rcpRatioy);

ECode IppYCbCr422ResizeCopy(
    unsigned char * pYSrc, unsigned char * pCbSrc, unsigned char * pCrSrc,
    unsigned char * pYDst,  unsigned char * pCbDst, unsigned char * pCrDst,
    int srcWidth, int srcHeight,
    int dstWidth, int dstHeight)
{
#if 0
    // TEST CODE, BECAUSE OF NO IPP LIBRARIES NOW.
    int i;
    unsigned char * pYSrcPos, *pCbSrcPos, *pCrSrcPos;
    unsigned char * pYDstPos, *pCbDstPos, *pCrDstPos;
    int nCopyLineY, nCopyLineCbCr;
    int srcBytesCbCr, dstBytesCbCr;
    int nCopyLines;

    nCopyLineY = dstWidth < srcWidth ? dstWidth : srcWidth;
    nCopyLineCbCr = nCopyLineY >> 1;
    srcBytesCbCr = srcWidth >> 1;
    dstBytesCbCr = dstWidth >> 1;
    nCopyLines = dstHeight < srcHeight ? dstHeight : srcHeight;

    pYSrcPos = pYSrc;
    pCbSrcPos = pCbSrc;
    pCrSrcPos = pCrSrc;
    pYDstPos = pYDst;
    pCbDstPos = pCbDst;
    pCrDstPos = pCrDst;

    for (i = 0; i < nCopyLines; i++) {
        memcpy(pYDstPos, pYSrcPos, nCopyLineY);
        memcpy(pCbDstPos, pCbSrcPos, nCopyLineCbCr);
        memcpy(pCrDstPos, pCrSrcPos, nCopyLineCbCr);

        pYDstPos += dstWidth;
        pYSrcPos += srcWidth;
        pCbDstPos += dstBytesCbCr;
        pCbSrcPos += srcBytesCbCr;
        pCrDstPos += dstBytesCbCr;
        pCrSrcPos += srcBytesCbCr;
    }
#else
    // RIGHT CODE, USING IPP
    Ipp8u *p8uDst[3];
    IppiSize srcSize, dstSize;
    IppCameraRotation rotation;
    IppCameraInterpolation interpolation;
    int rcpRatioX, rcpRatioY;
    int srcStep[3], dstStep[3];
    int status = ippStsNoErr;

    int w2;
    int h2;
    int w3;
    int h3;

    Ipp8u *p8uSrc[3];

//    DBGOUT(kprintf("IppResizeCopy: dstWidth = %d, dstHeight = %d, "
//        "pSrc->width = %d, pSrc->height = %d\n",
//        dstWidth, dstHeight, srcWidth, srcHeight));
    if(dstWidth <= 0 || dstHeight <= 0) {
        return E_INVALID_ARGUMENT;
    }

    /* Initialize parameters */
    w2 = ((srcWidth + 1) >> 1);
    h2 = ((srcHeight + 1) >> 0);
    w3 = ((dstWidth + 1) >> 1);
    h3 = ((dstHeight + 1) >> 0);

    srcSize.width = srcWidth;
    srcSize.height = srcHeight;
    dstSize.width = dstWidth;
    dstSize.height = dstHeight;

    srcStep[0] = srcWidth;
    srcStep[1] = w2;
    srcStep[2] = w2;
    dstStep[0] = dstWidth;
    dstStep[1] = w3;
    dstStep[2] = w3;

    interpolation = ippCameraInterpNearearest;//  ippCameraInterpBilinear;
    rotation = ippCameraRotateDisable;

    rcpRatioX =
        (int)((((srcSize.width-1)<<16))/ (dstSize.width - 1));
    rcpRatioY =
        (int)((((srcSize.height-1)<<16)) / (dstSize.height - 1));

//    DBGOUT(kprintf("IppResizeCopy: rcpRatioX = %d, rcpRatioY = %d\n",
//        rcpRatioX, rcpRatioY));

    p8uSrc[0] = (Ipp8u*)pYSrc,
    p8uSrc[1] = (Ipp8u*)pCbSrc,
    p8uSrc[2] = (Ipp8u*)pCrSrc;

    p8uDst[0] = (Ipp8u*)_ALIGN4(pYDst),
    p8uDst[1] = (Ipp8u*)pCbDst,
    p8uDst[2] = (Ipp8u*)pCrDst;

    // This function is invoked in ISR now, and it will changed WMMX registers
    // (in ipp call), so the current WMMX registers should be saved.
    // Save current WMMX registers:
    SaveWMMXRegisters(g_pMmxData, &s_dummyFlag);

    /* resize & rotate */
    status = ASM_ippiYCbCr422RszRot_8u_P3R(
        (const unsigned char **)p8uSrc, srcStep, srcSize, p8uDst, dstStep, dstSize,
        interpolation, rotation, rcpRatioX, rcpRatioY);
//    DBGOUT(kprintf("IppResizeCopy: status = %d\n", status));

    // Load saved WMMX registers:
    RestoreWMMXRegisters(g_pMmxData);


#endif

    return NOERROR;
}
